package com.seari.tunnel.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

import org.springframework.stereotype.Service;
import org.w3c.dom.NodeList;

import com.seari.tunnel.entity.job.BrowseElement;
import com.seari.tunnel.entity.job.BrowseResponse;
import com.seari.tunnel.entity.job.ItemValue;
import com.seari.tunnel.entity.job.OPCData;
import com.seari.tunnel.entity.job.ReadRequestItem;
import com.seari.tunnel.entity.job.ReadRequestItemList;
import com.seari.tunnel.entity.job.ReadResponse;
import com.seari.tunnel.service.IJOBService;

@Service(IJOBService.SERVICE_NAME)
public class JOBServiceImpl implements IJOBService{
	public static String endpoint = "http://127.0.0.1:81/soap";
	private static final String namespace = "http://opcfoundation.org/webservices/XMLDA/1.0/";

	@Override
	public String read(List<OPCData> opcDataList) throws SOAPException,
			IOException, JAXBException {
		if (opcDataList == null) {
    		throw new NullPointerException("opcDataList can not be null");
    	}
    	
    	 //  创建消息对象   
        // ===========================================   
        SOAPMessage message = MessageFactory.newInstance().createMessage();
        SOAPHeader header = message.getSOAPHeader();
        header.detachNode();
        
        MimeHeaders mh = message.getMimeHeaders();
        mh.addHeader("SOAPAction", "http://opcfoundation.org/webservices/XMLDA/1.0/Read"); 
 
        // 获取soap的信封
        SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
        envelope.setPrefix("soap");
 
        // 获取消息的body
        SOAPBody body = message.getSOAPBody();
        body.setPrefix("soap");
        QName bodyName =  new QName(namespace, "Read");
        SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
        
        SOAPElement se = bodyElement.addChildElement("Options");
        se.setAttribute("LocaleID", "en-US");
        se.setAttribute("ClientRequestHandle", "");
        se.setAttribute("ReturnItemTime", "true");
        se.setAttribute("ReturnItemName", "true");
        
        se = bodyElement.addChildElement("ItemList");
        
        ReadRequestItemList reqItemList = new ReadRequestItemList();
        int len = opcDataList.size();
        List<ReadRequestItem> items = reqItemList.getItems();
        List<ReadRequestItem> items2 = new ArrayList<ReadRequestItem>(len);
        items.addAll(items2);
         
        SOAPElement itemsElem = null;
        ReadRequestItem item = null;
        for (int i = 0; i < len; i++) {
        	item = new ReadRequestItem();
        	items.add(i, item);
        	item.setClientItemHandle(String.valueOf(i)); 
        	item.setItemName(opcDataList.get(i).getOPCName());
        	
        	itemsElem = se.addChildElement("Items");
        	itemsElem.setAttribute("ItemName", item.getItemName());
        	itemsElem.setAttribute("ClientItemHandle", item.getClientItemHandle());
        }
        
        SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
        SOAPMessage response = connection.call(message, endpoint);
        connection.close();
 
        SOAPBody responseBody = response.getSOAPBody();
        NodeList list = responseBody.getChildNodes();
        JAXBContext jaxbContext = JAXBContext.newInstance(ReadResponse.class); 
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();  
        ReadResponse readResponse = (ReadResponse) jaxbUnmarshaller.unmarshal(list.item(1));
        List<ItemValue> replyItems = readResponse.getRItemList().getItems();
        
        if (replyItems.size() > 0)
        {
        	int n = 0;
        	OPCData opcdata = null;
        	for (ItemValue v : replyItems) {
        		n = Integer.parseInt(v.getClientItemHandle());
        		opcdata = opcDataList.get(n);
        		opcdata.setOPCValue(v.getValue().toString());
        		opcdata.setOPCTime(v.getTimestamp().toString().replace('T', ' '));
        	}
        }
 
        try {
            
//          System.out.println(getXmlFromSOAPMessage(message));
//          System.out.println(getXmlFromSOAPMessage(response));
            
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
		return "";
	}

	@Override
	public void write(String itemName, String szValue) throws SOAPException,
			IOException, JAXBException {
		
			SOAPMessage message = MessageFactory.newInstance().createMessage();
			SOAPHeader header = message.getSOAPHeader();
			header.detachNode();

			MimeHeaders mh = message.getMimeHeaders();
			mh.addHeader("SOAPAction",
					"http://opcfoundation.org/webservices/XMLDA/1.0/Write");

			// 获取soap的信封
			SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
			envelope.setPrefix("soap");

			// 获取消息的body
			SOAPBody body = message.getSOAPBody();
			body.setPrefix("soap");
			QName bodyName = new QName(namespace, "Write");
			SOAPBodyElement bodyElement = body.addBodyElement(bodyName);

			SOAPElement se = bodyElement.addChildElement("Options");
			se.setAttribute("LocaleID", "en-US");
			se.setAttribute("ClientRequestHandle", "");
			se.setAttribute("ReturnItemTime", "false");
			se.setAttribute("ReturnItemName", "false");

			se = bodyElement.addChildElement("ItemList");

			se = se.addChildElement("Items");
			se.setAttribute("ItemName", itemName);
			se.setAttribute("ClientItemHandle", "");

			se = se.addChildElement("Value");
			se.addTextNode(szValue);


				SOAPConnection connection = SOAPConnectionFactory.newInstance()
						.createConnection();
				SOAPMessage response = connection.call(message, endpoint);
				connection.close();
		
	}

	@Override
	public List<OPCData> browse(String itemName, List<OPCData> opcDataList)
			throws SOAPException, IOException, JAXBException {
    	 //  创建消息对象   
        // ===========================================   
        SOAPMessage message = MessageFactory.newInstance().createMessage();
        SOAPHeader header = message.getSOAPHeader();
        header.detachNode();
        
        MimeHeaders mh = message.getMimeHeaders();
        mh.addHeader("SOAPAction", "http://opcfoundation.org/webservices/XMLDA/1.0/Browse"); 
 
        // 获取soap的信封
        SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
        envelope.setPrefix("soap");
        // 获取消息的body
        SOAPBody body = message.getSOAPBody();
        body.setPrefix("soap");
        
        QName bodyName =  new QName(namespace, "Browse");
        SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
        
        bodyElement.setAttribute("LocaleID", "en-US");
        bodyElement.setAttribute("ClientRequestHandle", "");
        bodyElement.setAttribute("ItemName", itemName);
        bodyElement.setAttribute("MaxElementsReturned", "500");
        bodyElement.setAttribute("ElementNameFilter", "");
        bodyElement.setAttribute("VendorFilter", "");
        bodyElement.setAttribute("ReturnErrorText", "true");
        
        
        
        SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
        SOAPMessage response = connection.call(message, endpoint);
        connection.close();
 
        SOAPBody responseBody = response.getSOAPBody();
        NodeList list = responseBody.getChildNodes();
        JAXBContext jaxbContext = JAXBContext.newInstance(BrowseResponse.class); 
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();  
        BrowseResponse browseResponse = (BrowseResponse) jaxbUnmarshaller.unmarshal(list.item(1));
        List<BrowseElement> elmList = browseResponse.getElements();
        int len = elmList.size();
        BrowseElement tmpbe = null;
        for (int i = 0; i < len; i++) {
        	tmpbe = elmList.get(i);
        	if (tmpbe != null)
            {
                if (tmpbe.isIsItem() == true)		// Item
                {
                    String szTemp = tmpbe.getItemName();
                    if (szTemp.indexOf("$") == -1)
                    {
                        OPCData data = new OPCData();
                        data.setOPCName( tmpbe.getItemName() );
                        opcDataList.add(data);
                        
                    }
                }
                else		// Branch
                {
                    if ( !"".equals(tmpbe.getItemName()))
                    {
                    	browse(tmpbe.getItemName(), opcDataList);
                    }
                }
            }
        	
        	
        }
        
        
 
        try {
            
//          System.out.println(getXmlFromSOAPMessage(message));
//          System.out.println(getXmlFromSOAPMessage(response));
            
        } catch (Exception e) {
            e.printStackTrace();
        }
		return opcDataList;
	}
	
}
